/* readconf/readconf.c 
 * 
 * This file is part of readconf. 
 * 
 * readconf is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version. 
 * 
 * readconf is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with readconf. If not, see <https://www.gnu.org/licenses/>
 */ 




#include <readconf/readconf.h>
#include <readconf/port.h>

#include <readconf/do_op_set.h>


/* returns zero if success, -1 if eof */
static int parse_line(void);

/* fill a line splits by READCONF_LINE_SPLIT. returns 0 if end of file. */
static int read_line(void);

char *line_buffer;
int line_no = 0;


struct readconf_op ops[] = {
	{
		"set", 3, do_op_set
	}, 

	{
		"show", 4, show_names
	}, 

	{
		"", 0, NULL
	}
};




int readconf_init(void) {
	line_buffer = readconf_malloc(READCONF_MAXLINESIZE);

	if (!line_buffer) {
		readconf_error("libreadconf: failed to allocate line buffer. \n");

		return 1;
	}

	while (!parse_line());

	free(line_buffer);
	
	return 0;
}


static int parse_line(void) {
	struct readconf_op *o;

	if (!read_line()) 
		return 1;


	for (o = ops; o->do_op; o++) 
		if (!strncmp(line_buffer, o->op, o->oplen)) 
			return o->do_op();

	readconf_errorf("no valid op found");
	
	return 1;
}



static int read_line(void) {
	int i;
	char c;

	memset(line_buffer, 0x00, READCONF_MAXLINESIZE);

	for (i = 0; i < READCONF_MAXLINESIZE; i++) {
		c = 0;
		line_buffer[i] = c = readconf_getbyte();

		if (c == READCONF_LINE_SPLIT) {
			line_buffer[i] = 0;
			line_no++;

			if (!i) 
				return read_line();

			return i;
		}

		else if (c == READCONF_COMMENT) {
			while (c != READCONF_LINE_SPLIT) 
				if (!(c = readconf_getbyte())) 
					/* when comment at end of file */
					return 0;

			line_no++;
			return read_line();
		}

		else if (c == -1) 
			return 0;
	}

	return 0;
}



static const char *whitespace = READCONF_WHITESPACE;


char *skip_space(char *buffer) {
	int i;

	for (i = 0; i < READCONF_MAXLINESIZE; i++) {
		int j;

		for (j = 0; whitespace[j]; j++) 
			if (buffer[i] == whitespace[j]) 
				break;

		if (!whitespace[j]) 
			return buffer + i;
	}

	return NULL;
}


int len_of(char *start) {
	register int i;
	
	for (i = 0; i < READCONF_MAXLINESIZE; i++) {
		int j;

		if (!start[i]) 
			return i;

		for (j = 0; whitespace[j]; j++) 
			if (start[i] == whitespace[j]) 
				break;

		if (whitespace[j]) 
			return i;
	}

	return 0;
}


